001 /* 002 * Copyright 2005 Stephen J. McConnell. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package net.dpml.station.server; 020 021 import java.net.URI; 022 import java.net.URL; 023 import java.rmi.registry.Registry; 024 025 import net.dpml.cli.Option; 026 import net.dpml.cli.Group; 027 import net.dpml.cli.CommandLine; 028 import net.dpml.cli.OptionException; 029 import net.dpml.cli.commandline.Parser; 030 import net.dpml.cli.builder.ArgumentBuilder; 031 import net.dpml.cli.builder.GroupBuilder; 032 import net.dpml.cli.builder.DefaultOptionBuilder; 033 import net.dpml.cli.option.PropertyOption; 034 import net.dpml.cli.validation.URIValidator; 035 import net.dpml.cli.validation.NumberValidator; 036 037 import net.dpml.station.ApplicationRegistry; 038 039 import net.dpml.transit.Artifact; 040 import net.dpml.transit.model.TransitModel; 041 042 import net.dpml.util.Logger; 043 044 /** 045 * The RemoteStation is responsible for the establishment of 046 * callback monitors to external processes established by the 047 * station manager. 048 * 049 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 050 * @version 1.0.1 051 */ 052 public class StationServerPlugin implements Runnable 053 { 054 private final Logger m_logger; 055 private final CommandLine m_line; 056 private final TransitModel m_model; 057 058 private RemoteStation m_station; 059 060 /** 061 * Creation of a new station server plugin for station commandline 062 * handling. 063 * @param logger the assigned logging channel 064 * @param model the transit model 065 * @param args the command line arguments array 066 * @exception Exception if an error occurs 067 */ 068 public StationServerPlugin( Logger logger, TransitModel model, String[] args ) throws Exception 069 { 070 m_logger = logger; 071 m_model = model; 072 073 // parse the command group model 074 075 Parser parser = new Parser(); 076 parser.setGroup( COMMAND_GROUP ); 077 try 078 { 079 m_line = parser.parse( args ); 080 } 081 catch( OptionException e ) 082 { 083 final String message = "Server commandline processing error."; 084 StringBuffer buffer = new StringBuffer( message ); 085 buffer.append( "\nArgument count: " + args.length ); 086 for( int i=0; i<args.length; i++ ) 087 { 088 buffer.append( "\n arg (" + i + "): [" + args[i] + "]" ); 089 } 090 String error = buffer.toString(); 091 throw new Exception( error, e ); 092 } 093 } 094 095 /** 096 * Start the thread. 097 */ 098 public void run() 099 { 100 try 101 { 102 int port = getPortValue( m_line, Registry.REGISTRY_PORT ); 103 URI uri = (URI) m_line.getValue( URI_OPTION, null ); 104 if( null == uri ) 105 { 106 URL url = ApplicationRegistry.DEFAULT_STORAGE_URI.toURL(); 107 m_logger.info( "starting station on port: " + port ); 108 m_station = new RemoteStation( m_logger, m_model, port, url ); 109 Thread.currentThread().setContextClassLoader( ApplicationRegistry.class.getClassLoader() ); 110 setShutdownHook( m_station ); 111 } 112 else 113 { 114 if( Artifact.isRecognized( uri ) ) 115 { 116 URL url = Artifact.createArtifact( uri ).toURL(); 117 m_logger.info( 118 "starting station on port: " 119 + port 120 + " with registry " 121 + url ); 122 m_station = new RemoteStation( m_logger, m_model, port, url ); 123 } 124 else 125 { 126 URL url = uri.toURL(); 127 m_logger.info( 128 "starting station on port: " 129 + port 130 + " with registry " 131 + url ); 132 m_station = new RemoteStation( m_logger, m_model, port, url ); 133 } 134 } 135 } 136 catch( Exception e ) 137 { 138 final String error = 139 "Station startup failure."; 140 m_logger.error( error, e ); 141 } 142 } 143 144 private int getPortValue( CommandLine line, int defaultPort ) 145 { 146 if( line.hasOption( PORT_OPTION ) ) 147 { 148 Number number = (Number) line.getValue( PORT_OPTION, null ); 149 return number.intValue(); 150 } 151 else 152 { 153 return defaultPort; 154 } 155 } 156 157 private URI getRegistryURI( CommandLine line, URI uri ) 158 { 159 if( line.hasOption( URI_OPTION ) ) 160 { 161 return (URI) line.getValue( URI_OPTION, null ); 162 } 163 else 164 { 165 return uri; 166 } 167 } 168 169 /** 170 * Create a shutdown hook that will trigger shutdown of the station. 171 * @param station the station 172 */ 173 public static void setShutdownHook( final RemoteStation station ) 174 { 175 Runtime.getRuntime().addShutdownHook( new ShutdownHandler( station ) ); 176 } 177 178 private static final DefaultOptionBuilder OPTION_BUILDER = new DefaultOptionBuilder(); 179 private static final ArgumentBuilder ARGUMENT_BUILDER = new ArgumentBuilder(); 180 private static final GroupBuilder GROUP_BUILDER = new GroupBuilder(); 181 182 private static final PropertyOption PROPERTY_OPTION = new PropertyOption(); 183 private static final NumberValidator NUMBER_VALIDATOR = NumberValidator.getIntegerInstance(); 184 185 private static final Option PORT_OPTION = 186 ARGUMENT_BUILDER 187 .withDescription( "Port number." ) 188 .withName( "port" ) 189 .withMinimum( 0 ) 190 .withMaximum( 1 ) 191 .withValidator( NUMBER_VALIDATOR ) 192 .create(); 193 194 private static final Option URI_OPTION = 195 OPTION_BUILDER 196 .withShortName( "registry" ) 197 .withDescription( "Application registry store." ) 198 .withRequired( false ) 199 .withArgument( 200 ARGUMENT_BUILDER 201 .withDescription( "Local or remote artifact reference." ) 202 .withName( "artifact" ) 203 .withMinimum( 1 ) 204 .withMaximum( 1 ) 205 .withValidator( new URIValidator() ) 206 .create() ) 207 .create(); 208 209 private static final Group COMMAND_GROUP = 210 GROUP_BUILDER 211 .withName( "options" ) 212 .withOption( PORT_OPTION ) 213 .withOption( URI_OPTION ) 214 .withOption( PROPERTY_OPTION ) 215 .create(); 216 217 /** 218 * Shutdown handler implementation. 219 */ 220 private static class ShutdownHandler extends Thread 221 { 222 private final RemoteStation m_station; 223 224 /** 225 * Creation of a new shutdown handler. 226 * @param station the station to shutdown 227 */ 228 ShutdownHandler( final RemoteStation station ) 229 { 230 m_station = station; 231 } 232 233 public void run() 234 { 235 m_station.shutdown(); 236 } 237 } 238 239 }